package com.viknix.threadpool.manager.client.factory;

import cn.hutool.core.collection.CollUtil;
import com.viknix.threadpool.manager.client.enums.RejectedTypeEnum;
import com.viknix.threadpool.manager.client.exception.TpmProcessException;
import com.viknix.threadpool.manager.client.spi.CustomRejectedHandler;
import com.viknix.threadpool.manager.client.spi.TpServiceLoader;
import org.apache.commons.lang3.StringUtils;

import java.util.Collection;
import java.util.Objects;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;

import static com.viknix.threadpool.manager.client.enums.RejectedTypeEnum.*;

/**
 * @Author: Dongqi
 * @Date: 2021/10/27 11:22
 * @Version 1.0
 * @Description: 拒绝策略工厂
 */
public class RejectedHandlerFactory {

    public static RejectedExecutionHandler createPolicy(int code) {

        RejectedExecutionHandler handler = null;
        if (Objects.equals(code, CALLER_RUNS_POLICY.getCode())) {
            handler = new ThreadPoolExecutor.CallerRunsPolicy();
        } else if (Objects.equals(code, ABORT_POLICY.getCode())) {
            handler = new ThreadPoolExecutor.AbortPolicy();
        } else if (Objects.equals(code, DISCARD_POLICY.getCode())) {
            handler = new ThreadPoolExecutor.DiscardPolicy();
        } else if (Objects.equals(code, DISCARD_OLDEST_POLICY.getCode())) {
            handler = new ThreadPoolExecutor.DiscardOldestPolicy();
        }
        if (handler != null) {
            return handler;
        }

        Collection<CustomRejectedHandler> customRejectedHandlers = TpServiceLoader.getSingletonServiceInstances(CustomRejectedHandler.class);
        if (CollUtil.isEmpty(customRejectedHandlers)) {
            throw new TpmProcessException("拒绝策略生产异常！");
        }
        handler = customRejectedHandlers.stream()
                .filter(each -> Objects.equals(code, each.getCode()))
                .map(each -> each.generateRejected())
                .findFirst()
                .orElseThrow(() -> new TpmProcessException("拒绝策略生产异常！"));
        return handler;
    }

    public static String getNameByCode(Integer code) {

        String name = RejectedTypeEnum.getNameByCode(code);
        if (StringUtils.isNotBlank(name)) {
            return name;
        }
        Collection<CustomRejectedHandler> customRejectedHandlers = TpServiceLoader.getSingletonServiceInstances(CustomRejectedHandler.class);
        if (CollUtil.isEmpty(customRejectedHandlers)) {
            throw new TpmProcessException("拒绝策略生产异常！");
        }
        name = customRejectedHandlers.stream()
                .filter(each -> Objects.equals(code, each.getCode()))
                .map(each -> each.getName())
                .findFirst()
                .orElseThrow(() -> new TpmProcessException("拒绝策略生产异常！"));
        return name;
    }
}
